package aufgabe2;

import java.util.*;

import aufgabe2.MatrixArrayListe.Pair;
import aufgabe2.MatrixListe.Triple;

public class Modul {

	// +++++++++++++Init++++++++++++++++++++

	// #############2D Arrays###############

	private static MatrixArray ma1 = createMA(3, 0.0);
	private static MatrixArray ma2 = createMA(3, 0.0);

	private static MatrixArray ma3 = createMA(10, 0.0);
	private static MatrixArray ma4 = createMA(10, 0.0);

	private static MatrixArray ma5 = createMA(50, 0.0);
	private static MatrixArray ma6 = createMA(50, 0.0);

	private static MatrixArray ma7 = createMA(100, 0.0);
	private static MatrixArray ma8 = createMA(100, 0.0);

	// #########MatrixArrayListe (Pair)######

	private static MatrixArrayListe mal1 = createMAL(3, 0.0);
	private static MatrixArrayListe mal2 = createMAL(3, 0.0);

	private static MatrixArrayListe mal3 = createMAL(10, 0.0);
	private static MatrixArrayListe mal4 = createMAL(10, 0.0);

	private static MatrixArrayListe mal5 = createMAL(50, 0.0);
	private static MatrixArrayListe mal6 = createMAL(50, 0.0);

	private static MatrixArrayListe mal7 = createMAL(100, 0.0);
	private static MatrixArrayListe mal8 = createMAL(100, 0.0);

	// ##########MatrixListe (Triple)#########

	private static MatrixListe ml1 = createML(3, 0.0);
	private static MatrixListe ml2 = createML(3, 0.0);

	private static MatrixListe ml3 = createML(10, 0.0);
	private static MatrixListe ml4 = createML(10, 0.0);

	private static MatrixListe ml5 = createML(50, 0.0);
	private static MatrixListe ml6 = createML(50, 0.0);

	private static MatrixListe ml7 = createML(100, 0.0);
	private static MatrixListe ml8 = createML(100, 0.0);

	/**
	 * Erstellt eine zufällig generierte Matrix der Datenstruktur 2D Array.
	 * 
	 * @param dim
	 *            Dimension der quadratischen Matrix
	 * @param zufall
	 *            ZufallsFaktor der bestimmt ob ein Wert Aij ungleich Null ist.
	 * @return Eine zufällig generierte Matrix.
	 */
	public static MatrixArray createMA(int dim, double zufall) {
		double[][] m = new double[dim][dim];

		for (int i = 0; i < dim; i++) {
			for (int j = 0; j < dim; j++) {
				if (Math.random() > zufall) {
					int x = (int) (Math.random() * 10);
					m[i][j] = x;
				} else {
					m[i][j] = 0;
				}
			}

		}

		return new MatrixArray(m);
	}

	/**
	 * Erstellt eine zufällig generierte Matrix der Datenstruktur ArrayListe
	 * (Pair).
	 * 
	 * @param dim
	 *            Dimension der quadratischen Matrix
	 * @param zufall
	 *            ZufallsFaktor der bestimmt ob ein Wert Aij ungleich Null ist.
	 * @return Eine zufällig generierte Matrix.
	 */
	public static MatrixArrayListe createMAL(int dim, double zufall) {
		ArrayList<Pair>[] matrix = new ArrayList[dim];
		for (int i = 0; i < dim; i++) {
			matrix[i] = new ArrayList<Pair>();
		}
		for (int i = 0; i < dim; i++) {
			ArrayList<Pair> a1 = new ArrayList<Pair>();
			for (int j = 0; j < dim; j++) {
				if (Math.random() > zufall) {
					int x = (int) (Math.random() * 10);
					a1.add(new Pair(j, x));
				}
			}
			matrix[i] = a1;
		}
		return new MatrixArrayListe(matrix, dim, dim);
	}

	/**
	 * Erstellt eine zufällig generierte Matrix der Datenstruktur Liste(Triple).
	 * 
	 * @param dim
	 *            Dimension der quadratischen Matrix
	 * @param zufall
	 *            ZufallsFaktor der bestimmt ob ein Wert Aij ungleich Null ist.
	 * @return Eine zufällig generierte Matrix.
	 */
	public static MatrixListe createML(int dim, double zufall) {
		ArrayList<Triple> l1 = new ArrayList<Triple>();
		for (int i = 0; i < dim; i++) {
			for (int j = 0; j < dim; j++) {
				if (Math.random() > zufall) {
					int x = (int) (Math.random() * 10);
					l1.add(new Triple(i, j, x));
				}
			}
		}
		return new MatrixListe(l1, dim, dim);
	}

	/**
	 * Testet die Laufzeit der Datenstruktur 2D Array anhand einer
	 * Matrixmultiplikation.
	 * 
	 * @param m1
	 *            Matrix 1
	 * @param m2
	 *            Matrix 2
	 * @return Die Zeit, die benötigt wurde, die Operation auszuführen in ms.
	 */
	public static double laufzeitTest(MatrixArray m1, MatrixArray m2) {

		// ################2D Array################

		double zstVorher;
		double zstNachher;
		double time;

		zstVorher = System.currentTimeMillis();
		m1.mul(m2);
		zstNachher = System.currentTimeMillis();

		time = (zstNachher - zstVorher);

		return time;
	}

	/**
	 * Testet die Laufzeit der Datenstruktur ArrayListe (Pair) anhand einer
	 * Matrixmultiplikation.
	 * 
	 * @param m1
	 *            Matrix 1
	 * @param m2
	 *            Matrix 2
	 * @return Die Zeit, die benötigt wurde, die Operation auszuführen in ms.
	 */
	public static double laufzeitTest(MatrixArrayListe m1, MatrixArrayListe m2) {

		// ################ArrayListe (Pair)################

		double zstVorher;
		double zstNachher;
		double time;

		zstVorher = System.currentTimeMillis();
		m1.mul(m2);
		zstNachher = System.currentTimeMillis();

		time = (zstNachher - zstVorher);

		return time;
	}

	/**
	 * Testet die Laufzeit der Datenstruktur Liste(Triple) anhand einer
	 * Matrixmultiplikation.
	 * 
	 * @param m1
	 *            Matrix 1
	 * @param m2
	 *            Matrix 2
	 * @return Die Zeit, die benötigt wurde, die Operation auszuführen in ms.
	 */
	public static double laufzeitTest(MatrixListe m1, MatrixListe m2) {

		// ################Liste (Triple)################

		double zstVorher;
		double zstNachher;
		double time;

		zstVorher = System.currentTimeMillis();
		m1.mul(m2);
		zstNachher = System.currentTimeMillis();

		time = (zstNachher - zstVorher);

		return time;
	}

	public static double mittelWert(double time, int counts) {
		double val;

		val = (time / counts);
		return val;
	}

	public static void main(String[] args) {

		// 2D Array Messvariablen
		double timeMA1 = 0.0;
		double timeMA2 = 0.0;
		double timeMA3 = 0.0;
		double timeMA4 = 0.0;

		// ArrayListe(Pair) Messvariablen
		double timeMAL1 = 0.0;
		double timeMAL2 = 0.0;
		double timeMAL3 = 0.0;
		double timeMAL4 = 0.0;

		// Liste(Triple) Messvariablen
		double timeML1 = 0.0;
		double timeML2 = 0.0;
		double timeML3 = 0.0;
		double timeML4 = 0.0;

		// #############Zeitmessungen############
		for (int i = 0; i < 10; i++) {

			// 2D Array Messungen aufsummieren
			timeMA1 += laufzeitTest(ma1, ma2);
			timeMA2 += laufzeitTest(ma3, ma4);
			timeMA3 += laufzeitTest(ma5, ma6);
			timeMA4 += laufzeitTest(ma7, ma8);

			// ArrayListe (Pair) Messungen aufsummieren
			timeMAL1 += laufzeitTest(mal1, mal2);
			timeMAL2 += laufzeitTest(mal3, mal4);
			timeMAL3 += laufzeitTest(mal5, mal6);
			timeMAL4 += laufzeitTest(mal7, mal8);

			// Liste(Triple) Messungen aufsummieren
			timeML1 += laufzeitTest(ml1, ml2);
			timeML2 += laufzeitTest(ml3, ml4);
			timeML3 += laufzeitTest(ml5, ml6);
			timeML4 += laufzeitTest(ml7, ml8);
		}

		// #######Mittelwert berehcnen 2D Array#############
		System.out.println("##########Mittelwerte 2D Array##########");
		System.out.println();
		System.out.println("Dimension: 3");
		System.out.println(mittelWert(timeMA1, 10));
		System.out.println("Dimension: 10");
		System.out.println(mittelWert(timeMA2, 10));
		System.out.println("Dimension: 50");
		System.out.println(mittelWert(timeMA3, 10));
		System.out.println("Dimension: 100");
		System.out.println(mittelWert(timeMA4, 10));
		System.out.println();

		// #######Mittelwert berehcnen ArrayListe(Pair)#############
		System.out.println("##########Mittelwerte ArrayListe(Pair)##########");
		System.out.println();
		System.out.println("Dimension: 3");
		System.out.println(mittelWert(timeMAL1, 10));
		System.out.println("Dimension: 10");
		System.out.println(mittelWert(timeMAL2, 10));
		System.out.println("Dimension: 50");
		System.out.println(mittelWert(timeMAL3, 10));
		System.out.println("Dimension: 100");
		System.out.println(mittelWert(timeMAL4, 10));
		System.out.println();

		// #######Mittelwert berehcnen Liste(Triple)#############
		System.out.println("##########Mittelwerte Liste(Triple)##########");
		System.out.println();
		System.out.println("Dimension: 3");
		System.out.println(mittelWert(timeML1, 10));
		System.out.println("Dimension: 10");
		System.out.println(mittelWert(timeML2, 10));
		System.out.println("Dimension: 50");
		System.out.println(mittelWert(timeML3, 10));
		System.out.println("Dimension: 100");
		System.out.println(mittelWert(timeML4, 10));
		System.out.println();
	}
}
